package ksv.cron.v1.impl;

import cn.hutool.core.util.RandomUtil;
import ksv.cron.CronContext;
import ksv.cron.CronCst;
import ksv.cron.bean.SysCron;
import ksv.cron.v1.ICron;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

/**
 * @创建人 wsdc
 * @时间 2021/2/1
 * @描述 临时的定时任务
 *  主调调用一次 生成这个实例 即可  这个保证只会在当前时间执行一次
 *  <li>    添加到阻塞队列中即可
 */
public class TemporaryCronImpl implements ICron {
    public static final DateTimeFormatter L_D_T_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    private SysCron sysCron;
    private CronContext currentContext;
    private LocalDateTime callTime;
    private String status = CronCst.CronTimeStatus.TEMPORARY;

    public TemporaryCronImpl(SysCron sysCron) {
        this.sysCron = sysCron;
        //  生成此时的上下文信息
        LocalDateTime localDateTime = LocalDateTime.now();

        currentContext = new CronContext();
        currentContext.setICron(this);
        currentContext.setUniqueKey(getClass().getSimpleName()+"@@@@=@@@@"+sysCron.getId()+"="+L_D_T_FORMAT.format(localDateTime)+ "@@@@random->"+ UUID.randomUUID().toString());
        callTime = localDateTime;
    }

    @Override
    public SysCron sysCron() {
        return sysCron;
    }

    @Override
    public CronContext nextContext() {
        return null;
    }

    @Override
    public CronContext currentContext() {
        return currentContext;
    }

    @Override
    public CronContext next() {
        currentContext = null;
        return currentContext;
    }

    @Override
    public long getDelay(TimeUnit unit) {
        //  距离当前时间还有多少时间才会执行
        LocalDateTime now = LocalDateTime.now();
        long second = Duration.between(now, callTime).getSeconds();
        long convert = unit.convert(second, TimeUnit.SECONDS);
        return convert;
    }

    @Override
    public int compareTo(Delayed o) {
        ICron o1 = (ICron) o;
        long seconds = Duration.between(o1.callTime(), callTime).getSeconds();
        return (int) seconds;
    }

    @Override
    public LocalDateTime callTime() {
        return callTime;
    }

    @Override
    public String status() {
        return status;
    }

    @Override
    public boolean shouldCheck() {
        return false;
    }
}
